﻿using System.Collections.Generic;
using System.Linq;
using GeoAPI.Geometries;
using GisSharpBlog.NetTopologySuite.Geometries;
using AzukiMap.Tools;

namespace AzukiMap.MapSource
{
    public class LocalVectorSource : VectorSource
    {
        public LocalVectorSource(VectorSourceTypes type)
            : base(type)
        {
            Init();
        }

        public LocalVectorSource(string name, VectorSourceTypes vectorType, int srid)
            : base(name, vectorType, srid)
        {
            Init();
        }

        // by Shimohana
        //public List<LocalVectorData> Items { get; set; }
        virtual public List<LocalVectorData> Items { get; set; }

        virtual protected void Init()
        {
            Items = new List<LocalVectorData>();
        }

        // by Shimohana
        virtual
        public void Add(LocalVectorData item)
        {
            if (item.Geometry != null)
                item.Geometry.SRID = Srid;

            Items.Add(item);
        }

        // by Shimohana
        virtual
        public void Remove(LocalVectorData item)
        {
            Items.Remove(item);
        }

        // by Shimohana
        virtual
        public void Clear()
        {
            Items.Clear();
        }

        public void SetMaxExtent()
        {
            double minXAll = double.PositiveInfinity;
            double maxXAll = double.NegativeInfinity;
            double minYAll = double.PositiveInfinity;
            double maxYAll = double.NegativeInfinity;
            foreach (LocalVectorData item in Items)
            {
                IGeometry geom = item.Geometry;
                IEnvelope env = geom.EnvelopeInternal;
                double minX = env.MinX;
                double minY = env.MinY;
                double maxX = env.MaxX;
                double maxY = env.MaxY;
                minXAll = (minX < minXAll) ? minX : minXAll;
                minYAll = (minY < minYAll) ? minY : minYAll;
                maxXAll = (maxX > maxXAll) ? maxX : maxXAll;
                maxYAll = (maxY > maxYAll) ? maxY : maxYAll;
            }
            if (minXAll != double.PositiveInfinity)
            {
                //IEnvelope extent = new Geometries.Envelope(minXAll, maxXAll, minYAll, maxYAll);
                MaxExtent = _geoUtil.CreateExtentPolygon(minXAll, maxXAll, minYAll, maxYAll);
            }
        }

        public IEnumerable<LocalVectorData> GetItemsInExtent(IPolygon extent)
        {
            foreach (LocalVectorData item in Items)
            {
                if (extent.Intersects(item.Geometry.Envelope))
                {
                    yield return item;
                }
            }
        }

        public IEnumerable<LocalVectorData> GetItemsInExtent(IMultiPolygon extent)
        {
            foreach (LocalVectorData item in Items)
            {
                if ( item.Geometry == null )
                    continue;

                if (extent.Intersects(item.Geometry.Envelope))
                {
                    yield return item;
                }
            }
        }

        public LocalVectorData GetSourceById(int id)
        {
            return Items.Where(item => item.Id == id).FirstOrDefault();
        }

        internal void TransformItems(int targetSrid)
        {
            var ct = TransformUtil.GetTransformation(Srid, targetSrid);
            foreach(LocalVectorData item in Items)
            {
                if ( item.Geometry == null )
                    continue;
                
                item.Geometry = TransformUtil.Transform((IGeometry)item.Geometry, ct);
                item.Geometry.SRID = targetSrid;
            }
            Srid = targetSrid;
        }
    }

    public class LocalVectorData
    {
        public object Attribute;
        public int ExpressionId = -1;
        public IGeometry Geometry;
        public int Id;
    }
}